"""
# -*- coding: utf-8 -*-
# @Time    : 2023/10/18 9:38
# @Author  : 王摇摆
# @FileName: cnn-bilstm.py
# @Software: PyCharm
# @Blog    ：https://blog.csdn.net/weixin_44943389?type=blog
"""

import matplotlib.pyplot as plt
import pandas as pd
import tensorflow as tf
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dropout, Bidirectional, LSTM, Dense
from tensorflow.keras.models import Sequential

# 0. 尽可能使用GPU加速训练
gpus = tf.config.experimental.list_physical_devices('GPU')
if gpus:
    try:
        # Allow memory growth for the GPU
        for gpu in gpus:
            tf.config.experimental.set_memory_growth(gpu, True)
        logical_gpus = tf.config.experimental.list_logical_devices('GPU')
        print(len(gpus), "Physical GPUs,", len(logical_gpus), "Logical GPUs")
    except RuntimeError as e:
        # Memory growth must be set before GPUs have been initialized
        print(e)

# 1. 读取数据
data = pd.read_csv('../dataset/train.csv')
test_data = pd.read_csv('../dataset/test.csv')
print('[1. 数据集加载完毕]')

# 2. 数据预处理
X = data.drop(columns=['id', 'target'])
y = data['target']

test_X = test_data.drop(columns='id')

X = X.values.reshape(-1, X.shape[1], 1)
test_X = test_X.values.reshape(-1, test_X.shape[1], 1)
print('[2. 数据集预处理完成]')

# 3. 初始化并构建CNN-BiLSTM模型
model = Sequential([
    Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(X.shape[1], 1)),
    MaxPooling1D(pool_size=2),

    Bidirectional(LSTM(64, return_sequences=True)),
    Dropout(0.2),

    Flatten(),
    Dense(128, activation='relu'),
    Dropout(0.2),

    Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# 5. 训练CNN-BiLSTM模型
history = model.fit(X, y, epochs=20, batch_size=32)
print('[3. 模型训练完成]')

# 6. 绘制曲线
loss = history.history['loss']
accuracy = history.history['accuracy']

epochs = range(1, len(loss) + 1)
plt.figure(figsize=(12, 4))

# 绘制损失值曲线
plt.subplot(1, 2, 1)
plt.plot(epochs, loss, 'b-', label='Training Loss')
plt.title('Training Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()

# 绘制准确率曲线
plt.subplot(1, 2, 2)
plt.plot(epochs, accuracy, 'b-', label='Training Accuracy')
plt.title('Training Accuracy')
plt.xlabel('Epochs')
plt.ylabel('Accuracy')
plt.legend()

plt.tight_layout()
plt.show()

# 6. 预测
# y_pred = model.predict(test_X)
# y_pred = (y_pred > 0.5).astype(int).reshape(-1)

# # 7. 预测结果输出
# pd.DataFrame({'id': test_data['id'], 'target': y_pred}).to_csv('../result/RNN.csv', index=None)
# print('[3. 预测结果已输出为CSV文件]')
